import axios from 'axios'
import {
  HttpExceptionTypeEnum,
  HttpHandleTypeEnum,
  HttpRequestTypeEnum,
} from '@/common/enum/enum_mediator.ts'
import { type ComponentCustomProperties } from '@vue/runtime-core'

// Axios 操作者
export class AxiosOperator {
  //region # 字段及构造器

  // 应用程序全局属性
  private appGlobalProperties: ComponentCustomProperties

  // 根目录
  private baseUrl: string

  // 默认配置
  // eslint-disable-next-line
  private defaultConfig: any

  /**
   * 有参构造器
   * @param appGlobalProperties
   * @param baseUrl - 根目录
   * */
  constructor(appGlobalProperties: ComponentCustomProperties, baseUrl: string) {
    this.baseUrl = baseUrl
    this.appGlobalProperties = appGlobalProperties

    this.init()
  }

  //endregion

  //region # 方法

  // Public

  /**
   * Get 请求
   * @param url 请求地址
   * @param data 请求数据
   * @param customErrorMessage 自定义错误消息
   * */
  public async get<TI, TO>(url: string, data: TI, customErrorMessage: string = ''): Promise<TO> {
    return await this.request(HttpRequestTypeEnum.get, url, data, customErrorMessage)
  }

  /**
   * Post 请求
   * @param url 请求地址
   * @param data 请求数据
   * @param customErrorMessage 自定义错误消息
   * */
  public async post<TI, TO>(url: string, data: TI, customErrorMessage: string = ''): Promise<TO> {
    return await this.request(HttpRequestTypeEnum.post, url, data, customErrorMessage)
  }

  // Private

  /**
   * 初始化
   * */
  private init(): void {
    // eslint-disable-next-line
    const that = this

    // 设置默认配置
    this.defaultConfig = {
      // Host地址
      baseURL: '',
      // Api地址
      url: '',
      // 请求头
      headers: {
        'Content-Type': 'application/json;charset=utf-8',
      },
      // 请求数据
      data: {},
      // 请求超时的毫秒数
      timeout: 0,
      // `auth` 表示应该使用 HTTP 基础验证，并提供凭据
      // 这将设置一个 `Authorization` 头，覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头
      // auth: {
      //     username: 'janedoe',
      //     password: 's00pers3cret'
      // },
      // 服务器响应的数据类型 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
      responseType: 'json',
      // 定义代理服务器
      // proxy: {
      //     host: '127.0.0.1',
      //     port: 9000,
      //     auth: {
      //         username: 'admin',
      //         password: 'admin'
      //     }
      // },
    }

    // 添加请求拦截器
    axios.interceptors.request.use(
      function (config) {
        // 在发送请求之前做些什么
        return config
      },
      function (error) {
        // 对请求错误做些什么
        return Promise.reject(error)
      },
    )

    // 添加响应拦截器
    axios.interceptors.response.use(
      // 处理请求成功
      // eslint-disable-next-line
      function (response: any) {
        return response.data ? response.data : response
      },
      // 异常处理
      // eslint-disable-next-line
      function (error: any) {
        return that.ResponseExceptionHandle(HttpHandleTypeEnum.response, error)
      },
    )
  }

  /**
   * 请求
   * @param method 请求方式
   * @param url 请求地址
   * @param data 请求数据
   * @param customErrorMessage 自定义错误消息
   * */
  private async request<TI, TO>(
    method: HttpRequestTypeEnum,
    url: string,
    data: TI,
    customErrorMessage: string = '',
  ): Promise<TO> {
    // 拼接完整地址
    const fullUrl = this.baseUrl + url

    // 设置请求头
    const headers = Object.assign(this.defaultConfig.headers, {})

    // 获取请求方式字符串
    const methodStr = this.appGlobalProperties.$enumFilters.httpRequestTypeFilter(method)

    // 设置配置项
    const config = Object.assign(this.defaultConfig, {
      // 请求地址
      url: fullUrl,
      // 请求方法
      method: methodStr,
      // 请求头
      headers,
      // 请求数据
      data: method == HttpRequestTypeEnum.get ? {} : data,
      params: method == HttpRequestTypeEnum.get ? data : {},
      // 自定义错误消息
      customErrorMessage,
    })

    // 执行请求
    const result: TO = await axios.request(config)
    return result
  }

  /**
   * 执行响应处理
   * @param response 响应信息
   * @param handleParam 处理参数
   * */
  // eslint-disable-next-line
  private resposeHandle(response: any, handleParam: any) {
    // 设置处理参数
    handleParam = Object.assign(
      {
        badRequestFunc: () => {},
        noPermissionFunc: () => {},
        timeOutFunc: () => {},
        serviceExceptionFunc: () => {},
        requestFailedFunc: () => {},
      },
      handleParam,
    )

    if (!response) {
      handleParam.requestFailedFunc()
      return
    }

    switch (response.status) {
      // 错误请求
      case 400:
      case 403:
      case 404:
        handleParam.badRequestFunc()
        break
      // 身份失效
      case 401:
        handleParam.noPermissionFunc()
        break
      // 请求超时
      case 408:
        handleParam.timeOutFunc()
        break
      // 服务器错误
      case 500:
        handleParam.serviceExceptionFunc()
        break
      // 其他错误
      default:
        handleParam.requestFailedFunc()
        break
    }
  }

  /**
   * 响应异常处理
   * @param type 处理类型
   * @param error 异常
   * */
  // eslint-disable-next-line
  private ResponseExceptionHandle(type: HttpHandleTypeEnum, error: any) {
    // 输出日志

    // 实例化 处理异常种类
    let errorMessage: string = ''

    // 执行响应处理
    this.resposeHandle(error.response, {
      // 错误请求
      badRequestFunc: () => {
        errorMessage = this.appGlobalProperties.$enumFilters.httpExceptionTypeFilter(
          HttpExceptionTypeEnum.badRequest,
        )
      },
      // 身份失效
      noPermissionFunc: () => {
        errorMessage = this.appGlobalProperties.$enumFilters.httpExceptionTypeFilter(
          HttpExceptionTypeEnum.noPermission,
        )
      },
      // 请求超时
      timeOutFunc: () => {
        errorMessage = this.appGlobalProperties.$enumFilters.httpExceptionTypeFilter(
          HttpExceptionTypeEnum.timeOut,
        )
      },
      // 服务器错误
      serviceExceptionFunc: () => {
        errorMessage = error.response.data
          ? error.response.data
          : this.appGlobalProperties.$enumFilters.httpExceptionTypeFilter(
              HttpExceptionTypeEnum.serviceException,
            )
      },
      // 其他错误
      requestFailedFunc: () => {
        errorMessage = error.response.data
          ? error.response.data
          : this.appGlobalProperties.$enumFilters.httpExceptionTypeFilter(
              HttpExceptionTypeEnum.requestFailed,
            )
      },
    })

    // 设置异常消息
    const customErrorMessage: string =
      error.response && error.response.config.customErrorMessage
        ? error.response.config.customErrorMessage
        : ''
    errorMessage = customErrorMessage != '' ? customErrorMessage : errorMessage

    // 打印日志
    console.log('[RequestError]：', errorMessage)
    console.log('RequestUrl:', `${error.response.request.responseURL}`)
    console.log('RequestMethod:', error.config.method)
    console.log('RequestKey:', '')
    console.log('RequestData:', error.config.data)
    console.log('RequestSettings:', error.config)
    console.log('ResponseStatus:', error.response.status)
    console.log('ResponseData:', error.response.data)
    console.log('--------')

    console.log(error)

    this.appGlobalProperties.$service.toast.error(errorMessage)

    // 终端当前 promise链
    return new Promise(() => {})
  }

  //endregion
}
